package top.codecrab.eblog.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.codecrab.eblog.dto.IpRegion;
import top.codecrab.eblog.entity.Sign;
import top.codecrab.eblog.entity.SignLog;
import top.codecrab.eblog.mapper.SignLogMapper;
import top.codecrab.eblog.mapper.SignMapper;
import top.codecrab.eblog.mapper.UserMapper;
import top.codecrab.eblog.service.SignRuleService;
import top.codecrab.eblog.service.SignService;
import top.codecrab.eblog.shiro.AccountProfile;
import top.codecrab.eblog.utils.IpRegionUtil;
import top.codecrab.eblog.utils.ShiroUtil;
import top.codecrab.eblog.vo.SignRankVo;
import top.codecrab.eblog.vo.SignVo;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author codecrab
 * @since 2022-03-18
 */
@Service
public class SignServiceImpl extends ServiceImpl<SignMapper, Sign> implements SignService {

    @Autowired
    private SignLogMapper signLogMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SignRuleService signRuleService;

    @Override
    public SignVo saveSignIn(HttpServletRequest request) {
        AccountProfile profile = ShiroUtil.getProfile();
        Long profileId = profile.getId();
        Sign sign = this.getOne(
            new QueryWrapper<Sign>()
                .eq("user_id", profileId)
        );

        String clientIp = ServletUtil.getClientIP(request);
        String address = IpRegionUtil.searchByBaiDu(clientIp);

        Sign newSign = new Sign();
        if (sign != null) {
            String day = DateUtil.format(sign.getModified(), "yyyy-MM-dd");
            // 获取的签到日期不能是当天的
            Assert.isFalse(DateTime.now().toString("yyyy-MM-dd").equals(day), "当天已经签到过了，请明天再来吧");

            DateTime date = DateTime.of(day, "yyyy-MM-dd");
            long betweenDay = DateUtil.betweenDay(DateTime.now(), date, true);
            if (betweenDay > 1) {
                newSign.setDays(1);
            } else {
                newSign.setDays(sign.getDays() + 1);
            }

            newSign.setId(sign.getId());
        } else {
            newSign.setDays(1);
            newSign.setUserId(profileId);
        }

        JSONObject info = new JSONObject();
        info.set("ip", clientIp);
        info.set("ipAddress", address);
        newSign.setInfo(info.toString());

        saveOrUpdate(newSign);

        Integer days = newSign.getDays();

        SignLog signLog = new SignLog();
        signLog.setSignId(newSign.getId());
        signLog.setUserId(profileId);
        signLog.setIp(clientIp);
        signLog.setIpAddress(address);
        // 从SignRule中获取要加的积分
        Integer point = signRuleService.getPointByDays(days);
        signLog.setPoint(point);
        signLogMapper.insert(signLog);

        // 给指定用户添加积分
        userMapper.updateAddPoint(profileId, point);

        profile.setIsSignIn(true);
        profile.setSignDays(days);
        profile.setSignPoint(point);
        ShiroUtil.setUser(profile);

        SignVo signVo = new SignVo();
        signVo.setSigned(true);
        signVo.setDays(days);
        signVo.setExperience(point);
        return signVo;
    }

    @Override
    public List<List<SignRankVo>> signRankList() {
        // 数据库的时区有问题，这里先传进去
        DateTime now = DateTime.now();

        // 获取最新签到
        List<SignRankVo> newTop = signLogMapper.selectCurrDayTop(now, "l.created", "DESC");

        // 获取今日最快
        List<SignRankVo> fastTop = signLogMapper.selectCurrDayTop(now, "l.created", "ASC");

        // 获取总签到榜
        List<SignRankVo> daysTop = baseMapper.selectTopList();

        return Arrays.asList(newTop, fastTop, daysTop);
    }
}
